package com.xjscrm.server.service.groupwelcome.impl;

import com.alibaba.fastjson.JSONObject;
import com.uzai.mobile.collect.api.dto.MicaTransDto;
import com.uzai.mobile.collect.api.dto.msg.MicaGroupMemberAddMsg;
import com.uzai.mobile.collect.api.dto.msg.MicaGroupMemberItemMsg;
import com.uzai.mobile.collect.api.enums.MicaMsgSource;
import com.xjscrm.common.entity.*;
import com.xjscrm.common.enums.RedisCacheKeyEnum;
import com.xjscrm.common.utils.Tools;
import com.xjscrm.common.vo.msg.MsgData;
import com.xjscrm.common.vo.operatorplandevice.OperatorPlanDeviceRule;
import com.xjscrm.server.common.util.DeviceTools;
import com.xjscrm.server.common.util.GroupTools;
import com.xjscrm.server.common.util.SleepTimeTools;
import com.xjscrm.server.enums.LimitRedisCacheKeyEnum;
import com.xjscrm.server.mapper.*;
import com.xjscrm.server.service.groupwelcome.GroupWelcomeService;
import com.xjscrm.server.service.msg.MsgSendService;
import com.xjscrm.server.vo.device.Device;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.time.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 企业微信群实现类
 *
 * @author makejava
 * @since 2024-03-01 17:01:12
 */
@Slf4j
@Service
public class GroupWelcomeServiceImpl implements GroupWelcomeService {
    @Autowired
    private WwGroupMapper wwGroupMapper;
    @Autowired
    private WwDeviceMapper wwDeviceMapper;
    @Autowired
    private GroupWelcomeMapper groupWelcomeMapper;
    @Autowired
    private GroupWelcomeDeviceMapper groupWelcomeDeviceMapper;
    @Autowired
    private WwGroupMemberMapper wwGroupMemberMapper;
    @Autowired
    private WwGroupTagsRelationMapper wwGroupTagsRelationMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private GroupWelcomeGroupMapper groupWelcomeGroupMapper;
    @Autowired
    private MsgSendService msgSendService;
    @Autowired
    private WwCustomerBlacklistMapper wwCustomerBlacklistMapper;

    /**
     * 针对进群等自动发送欢迎语
     *
     * @param micaTransDto
     * @return null
     * @author jitwxs
     * @date 2024/3/8 17:12
     */
    @Async("taskExecutorForEvent")
    public void groupWelcomeForGroupMemberAdd(MicaTransDto micaTransDto) {
        try {

            log.info("--监控系统日志--开始--");

            if (StringUtils.isBlank(micaTransDto.getDeviceId())) {
                log.info("机器人wxid is null, merId={}", micaTransDto.getMerId());
                return;
            }

            //查询该机器人
            WwDevice wwDevice = wwDeviceMapper.queryByDeviceId(micaTransDto.getDeviceId(), micaTransDto.getMerId());
            if (wwDevice == null) {
                return;
            }
            Device device = DeviceTools.transDevice(wwDevice);
            if (device == null) {
                return;
            }

            MicaGroupMemberAddMsg micaGroupMemberAddMsg = JSONObject.parseObject(micaTransDto.getData().toString(), MicaGroupMemberAddMsg.class);
            if(micaGroupMemberAddMsg == null){
                return;
            }

            //入群信息
            String groupId =  micaGroupMemberAddMsg.getGroupId();
            String groupName = micaGroupMemberAddMsg.getGroupName();
            List<MicaGroupMemberItemMsg> members = micaGroupMemberAddMsg.getMembers();
            if(StringUtils.isBlank(groupId) || StringUtils.isBlank(groupName)){
                return;
            }
            if(members == null || members.size() == 0){
                return;
            }

            //查询该机器人配置的所有智能回复
            List<GroupWelcomeDevice> groupWelcomeDeviceList = groupWelcomeDeviceMapper.selectByDeviceUniqueId(device.getDeviceUniqueId(), device.getMerId());
            if (groupWelcomeDeviceList == null || groupWelcomeDeviceList.size() == 0) {
                return;
            }

            //条件验证
            for (GroupWelcomeDevice groupWelcomeDevice : groupWelcomeDeviceList) {
                //验证条件
                GroupWelcome groupWelcome = groupWelcomeMapper.selectById(groupWelcomeDevice.getPlanId());
                if (groupWelcome != null) {
                    //循环进群成员
                    for (MicaGroupMemberItemMsg member : members) {
                        //默认黑名单不通过
                        WwCustomerBlacklist wwCustomerBlacklist = wwCustomerBlacklistMapper.selectByWxid(micaTransDto.getMerId(), member.getWxid());
                        if(wwCustomerBlacklist != null){ //在黑名单中
                            continue;
                        }

                        //验证条件
                        boolean result = verifyParaByGroupWelcome(groupWelcomeDevice, groupWelcome, micaGroupMemberAddMsg, device);
                        if (!result) {
                            continue;
                        }
                        //发送入群欢迎语
                        sendMsgByGroupWelcome(groupWelcomeDevice, groupWelcome, member, micaGroupMemberAddMsg, device);
                    }
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }finally {
            log.info("--监控系统日志--结束--");
        }
    }


    /**
     * 验证消息智能回复
     *
     * @param micaGroupMemberAddMsg 入群消息
     * @return 实例对象
     */
    private boolean verifyParaByGroupWelcome(GroupWelcomeDevice groupWelcomeDevice, GroupWelcome groupWelcome, MicaGroupMemberAddMsg micaGroupMemberAddMsg, Device device) {

        //入群信息
        String groupWxid =  micaGroupMemberAddMsg.getGroupId();
        String groupName = micaGroupMemberAddMsg.getGroupName();

        //验证触发机制
        boolean triggerResult = verifyTrigger(groupWelcome, groupWxid);
        if(!triggerResult){
            return false;
        }

        //验证休眠时间
        OperatorPlanDeviceRule operatorPlanDeviceRule = JSONObject.parseObject(groupWelcomeDevice.getRule(), OperatorPlanDeviceRule.class);
        //此时属于休眠时间
        boolean sleepTimeFlag = SleepTimeTools.verifySleepTime(operatorPlanDeviceRule);
        if(sleepTimeFlag){
            return false;
        }

        //获取群信息
        WwGroup wwGroup = wwGroupMapper.queryByDeviceUniqueIdAndGroupWxid(device.getId(), groupWxid);
        if (wwGroup == null) {
            return false;
        }
//        //查询机器人是否在群内
//        WwGroupMember wwGroupMember = wwGroupMemberMapper.selectByGroupWxidAndWxid(wwGroup.getMerId(), groupWxid, wwGroup.getDeviceId());
//        if(wwGroupMember == null){
//            return false;
//        }

        //群类型(0-全部群；1-筛选群；2-选择群)
        Integer groupType = Tools.getInteger(groupWelcome.getGroupType());
        if (groupType.intValue() == 1) { //部分群，则需要验证条件

            //群名关键词选项(0-含任意关键词；1-含所有关键词)
            Integer groupNameKeywordOpt = groupWelcome.getGroupNameKeywordOpt();
            if (groupNameKeywordOpt != null) {
                //群名关键词列表
                List<String> groupNameKeywordList = JSONObject.parseArray(groupWelcome.getGroupNameKeywords(), String.class);
                if (groupNameKeywordList == null || groupNameKeywordList.size() == 0) { //没有找到，则不回复
                    return false;
                }

                if (groupNameKeywordOpt.intValue() == 0) { //满足任意一个
                    boolean groupNameKeywordFlag = false;
                    for (String keyword : groupNameKeywordList) {
                        if (groupName.contains(keyword)) {//找到一个符合的，就返回通过
                            groupNameKeywordFlag = true;
                        }
                    }
                    if (!groupNameKeywordFlag) {
                        return false;
                    }
                } else {//满足所有触发
                    for (String keyword : groupNameKeywordList) {
                        if (!groupName.contains(keyword)) {//找到一个不符合的，就返回不通过
                            return false;
                        }
                    }
                }
            }

            //群标签选项(0-含任意标签；1-含所有标签；2-未打任何标签)
            Integer groupTagOpt = groupWelcome.getGroupTagOpt();
            if (groupTagOpt != null) {

                //封装此群已打的标签
                List<WwGroupTagsRelation> wwGroupTagsRelationList = wwGroupTagsRelationMapper.selectByDeviceIdAndGroupWxid(device.getMerId(), device.getDeviceId(), groupWxid);
                List<Long> wwGroupTagedList = new ArrayList<>();
                if (wwGroupTagsRelationList != null && wwGroupTagsRelationList.size() > 0) {
                    for (WwGroupTagsRelation wwGroupTagsRelation : wwGroupTagsRelationList) {
                        wwGroupTagedList.add(wwGroupTagsRelation.getTagId());
                    }
                }

                //2-未打任何标签
                if (groupTagOpt.intValue() == 2) {
                    if (wwGroupTagedList.size() > 0) {
                        return false;
                    }
                } else {
                    //标签列表
                    List<Long> groupTagList = JSONObject.parseArray(groupWelcome.getGroupTags(), Long.class);
                    if (groupTagList == null || groupTagList.size() == 0) { //没有找到，则不回复
                        return false;
                    }
                    if (groupTagOpt.intValue() == 0) { //满足任意一个
                        boolean tagFlag = false;
                        for (Long groupTag : groupTagList) {
                            if (wwGroupTagedList.contains(groupTag)) {//找到一个符合的，就返回通过
                                tagFlag = true;
                                break;
                            }
                        }
                        if (!tagFlag) {
                            return false;
                        }
                    } else if (groupTagOpt.intValue() == 1) {//满足所有触发
                        if (!wwGroupTagedList.containsAll(groupTagList)) {
                            return false;
                        }
                    }
                }
            }

            //群成员角色列表(0-群主；1-管理员；2-普通成员)
            String groupMemberIdentitys = groupWelcome.getGroupMemberIdentitys();
            List<Integer> groupMemberIdentityList = JSONObject.parseArray( groupMemberIdentitys, Integer.class);
            if (groupMemberIdentityList != null && groupMemberIdentityList.size() > 0) {
                boolean identityFlag = GroupTools.verifyIdentity(wwGroup, groupMemberIdentityList, device.getDeviceId());
                if (!identityFlag) {
                    return false;
                }
            }

            //验证群人数
            Integer groupMemberTotalMin = groupWelcome.getGroupMemberTotalMin();
            Integer groupMemberTotalMax = groupWelcome.getGroupMemberTotalMax();
            if (groupMemberTotalMin != null
                    && groupMemberTotalMax != null
                    && groupMemberTotalMin.intValue() <= groupMemberTotalMin.intValue()
            ) {
                //在群人数
                String groupMemberCountKey = String.format(RedisCacheKeyEnum.GROUP_MEMBER_COUNT.getKey(), groupWxid);
                Integer groupMemberCount =  (Integer)redisTemplate.opsForValue().get(groupMemberCountKey);
                Integer memberTotal = Tools.getInteger(groupMemberCount);
                if (memberTotal.intValue() < groupMemberTotalMin.intValue()
                        || memberTotal.intValue() > groupMemberTotalMax.intValue()
                ) {
                    return false;
                }
            }

            //验证建群时间
            String groupCreateDayStart = groupWelcome.getGroupCreateDayStart();
            String groupCreateDayEnd = groupWelcome.getGroupCreateDayEnd();
            if (StringUtils.isNotBlank(groupCreateDayStart)
                    && StringUtils.isNotBlank(groupCreateDayEnd)
            ) {
                Integer groupCreateTime = wwGroup.getGroupCreateTime();
                if (groupCreateTime == null) {//如果没有建群时间，则不通过
                    return false;
                }
                //判断旧发送时间是否在允许区间内
                Instant instant_groupCreateTime = Instant.ofEpochMilli(groupCreateTime * 1000L);
                LocalDateTime localDateTime = LocalDateTime.ofInstant(instant_groupCreateTime, ZoneId.systemDefault());
                boolean withinTimeInterval_groupCreateTime = Tools.isWithinDateInterval(localDateTime, LocalDate.parse(groupCreateDayStart), LocalDate.parse(groupCreateDayEnd));
                if (!withinTimeInterval_groupCreateTime) {
                    return false;
                }
            }
        }else if(groupType.intValue() == 2 ){//群类型(0-全部群；1-筛选群；2-选择群)
            //查询此群是否在配置中，如果不在，则返回false
            GroupWelcomeGroup groupWelcomeGroup = groupWelcomeGroupMapper.selectByPlanIdAndDeviceUniqueIdAndGroupWxid(groupWelcome.getId(), groupWelcomeDevice.getDeviceUniqueId(), groupWxid);
            if(groupWelcomeGroup == null ){
                return false;
            }
        }
        return true;
    }

    /**
     * 验证触发机制
     * 2个都不开启，则默认通过
     * 只开启任意一个，哪个开启就验证哪个
     *
     * @author jitwxs
     * @date 2024/4/14 14:09
     * @param groupWelcome
     * @return boolean
     */
    private boolean verifyTrigger(GroupWelcome groupWelcome, String groupWxid){
        //验证触发机制
        Integer triggerTimeSwitch = Tools.getInteger(groupWelcome.getTriggerTimeSwitch());
        Integer triggerCountSwitch = Tools.getInteger(groupWelcome.getTriggerCountSwitch());

        //2个都不开启，则直接通过
        if(triggerTimeSwitch.intValue() == 0 && triggerCountSwitch.intValue() == 0){
            return true;
        }

        //入群人数触发
        //是否开启入群人数触发
        if(triggerCountSwitch.intValue() == 1){//开启人数触发开关，则需要验证

            //获取当日缓存中的进群人数
            String limitGroupWelcomeMemberCountRedisKey = String.format(LimitRedisCacheKeyEnum.LIMIT_GROUP_WELCOME_MEMBER_COUNT.getKey(), groupWelcome.getId(), groupWxid);
            //每次有人进群则开启人数累加
            long leftTime = Tools.getSecondsTobeforedawn();
            //更新缓存
            redisTemplate.opsForValue().increment(limitGroupWelcomeMemberCountRedisKey);
            redisTemplate.expire(limitGroupWelcomeMemberCountRedisKey, leftTime, TimeUnit.SECONDS);

            Integer triggerCountCache = (Integer)redisTemplate.opsForValue().get(limitGroupWelcomeMemberCountRedisKey);
            triggerCountCache = Tools.getInteger(triggerCountCache);

            //配置的进群人数
            Integer triggerCount = Tools.getInteger(groupWelcome.getTriggerCount());
            if(triggerCountCache >= triggerCount){
                return true; //满足则通过
            }
        }

        //更新进群时间触发缓存
        if(triggerTimeSwitch.intValue() == 1) {//开启人数触发开关，则需要更新缓存
            //验证上次进群发送欢迎语时间
            String limitGroupWelcomeJoinTimeRedisKey = String.format(LimitRedisCacheKeyEnum.LIMIT_GROUP_WELCOME_JOIN_TIME.getKey(), groupWelcome.getId(), groupWxid);
            Object object = redisTemplate.opsForValue().get(limitGroupWelcomeJoinTimeRedisKey);
            if(object == null){
                return true; //查询上次进群缓存时间不存在，表示限制时间一国，则发送欢迎语
            }
        }

        return false;

    }


    /**
     * 入群发送欢迎语
     *
     * @param micaGroupMemberAddMsg 入群消息
     * @return 实例对象
     */
    private void sendMsgByGroupWelcome(GroupWelcomeDevice groupWelcomeDevice, GroupWelcome groupWelcome, MicaGroupMemberItemMsg member, MicaGroupMemberAddMsg micaGroupMemberAddMsg, Device device){
        try {
            //入群信息
            String groupWxid =  micaGroupMemberAddMsg.getGroupId();
            String wxid = member.getWxid();
            String nickname = member.getNickname();

            //发送方式(0-循序全部发送;1-随机一条发送)
            Integer sendType = Tools.getInteger(groupWelcome.getSendType());
            //封装发送的消息
            List<MsgData> msgDataList_send = new ArrayList<>();
            List<MsgData> msgDataList_config = JSONObject.parseArray(groupWelcome.getMsgDatas(), MsgData.class);
            if(msgDataList_config != null && msgDataList_config.size() > 0){
                if(sendType.intValue() == 1){ //随机一条
                    int rateMax = msgDataList_config.size() - 1;
                    int rateMin = 0;
                    //获取最小和最大时间的随机数（分数）
                    int rateRandom = (int) (Math.random() * (rateMax - rateMin + 1) + rateMin);
                    msgDataList_send.add(msgDataList_config.get(rateRandom));
                }else{
                    msgDataList_send = msgDataList_config;
                }

                //封装发送间隔时间
                Integer rateMin = Tools.getInteger(groupWelcomeDevice.getRateMin());
                Integer rateMax = Tools.getInteger(groupWelcomeDevice.getRateMax());
                for (MsgData msgData : msgDataList_send) {
                    //获取最小和最大时间的随机数（分数）
                    int rateRandom = (int) (Math.random() * (rateMax - rateMin + 1) + rateMin);
                    msgData.setGap(rateRandom); //随机时间
                    msgData.setUnit(1); //默认为秒
                }

                if(msgDataList_send != null && msgDataList_send.size() > 0){//有消息才发送
                    //发送入群欢迎语
                    msgSendService.msgSend(device, groupWxid, nickname, msgDataList_send, false, null, MicaMsgSource.JOIN_GROUP_WELCOME.getCode(), true);
                    //更新进群人数触发缓存
                    Integer triggerCountSwitch = Tools.getInteger(groupWelcome.getTriggerCountSwitch());
                    if(triggerCountSwitch.intValue() == 1){//开启人数触发开关，则需要更新缓存
                        //只要发送过入群欢迎语，则清空当前人数，重新开始计数
                        String limitGroupWelcomeMemberCountRedisKey = String.format(LimitRedisCacheKeyEnum.LIMIT_GROUP_WELCOME_MEMBER_COUNT.getKey(), groupWelcome.getId(), groupWxid);
                        redisTemplate.delete(limitGroupWelcomeMemberCountRedisKey);
                    }

                    //更新进群时间触发缓存
                    Integer triggerTimeSwitch = Tools.getInteger(groupWelcome.getTriggerTimeSwitch());
                    if(triggerTimeSwitch.intValue() == 1) {//开启人数触发开关，则需要更新缓存
                        Integer triggerTime = Tools.getInteger(groupWelcome.getTriggerTime());
                        //保存进群人数
                        String limitGroupWelcomeJoinTimeRedisKey = String.format(LimitRedisCacheKeyEnum.LIMIT_GROUP_WELCOME_JOIN_TIME.getKey(), groupWelcome.getId(), groupWxid);
                        redisTemplate.opsForValue().set(limitGroupWelcomeJoinTimeRedisKey, triggerTime,  triggerTime, TimeUnit.SECONDS);
                    }
                }
            }

        }catch (Exception e){
            log.error(e.getMessage(), e);
        }
    }

}
